package com.mccken.springframework.factory.support;

import java.lang.reflect.Constructor;

import com.mccken.springframework.BeansException;
import com.mccken.springframework.factory.config.BeanDefinition;

import lombok.Getter;
import lombok.Setter;

/**
 * @program: mccken-collect
 * @description:
 * @author: mccken
 * @create: 2022-11-19 23:03
 **/
public abstract class AbstractAutowiredCapableBeanFactory extends AbstractBeanFactory {
	
	@Getter
	@Setter
	private InstantiationStrategy instantiationStrategy = new CglibSubclassingInstantiationstrategy();
	
	@Override
	protected Object createBean(String beanName, BeanDefinition beanDefinition, Object... args) throws BeansException {
		Object bean = null;
		try {
			bean = createBeanInstance(beanDefinition, beanName, args);
		} catch(Exception e) {
			throw new BeansException("Instantiation of bean failed", e); 	
		}
		
		registerSingleton(beanName, bean);
		return bean;
	}

	protected Object createBeanInstance(BeanDefinition beanDefinition, String beanName, Object[] args) {
		Constructor constructorToUse = null;
		Class<?> beanClass = beanDefinition.getBeanClass();
		// 获取所有构造函数
		Constructor<?>[] declaredConstructors = beanClass.getDeclaredConstructors();
		for (Constructor<?> constructor : declaredConstructors) {
			if (null != args && constructor.getParameterTypes().length == args.length) {
				constructorToUse = constructor;
				break;
			}
		}
		
		return getInstantiationStrategy().instantiate(beanDefinition,beanName, constructorToUse, args);

	}
}
